package com.guan.snake;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

/**
 * 实现键盘监听接口,可引发对应行为
 *
 * @author caryguan
 * @version V1.0
 * @Package com.guan.snake
 * @date 2020/9/11 20:19
 */
public class GamePanel extends JPanel implements KeyListener, ActionListener {

    //贪吃蛇长度
    int length;

    //蛇的坐标X
    int[] snakeX = new int[600];

    //蛇的坐标Y
    int[] snakeY = new int[600];

    //定义蛇头朝向
    Integer direction = 1;

    //判断游戏是否开始,键盘控制
    boolean isStart = false;

    //实现定时器延迟为0.1s
    Timer timer = new Timer(100, this);

    //定义食物的坐标
    int foodX;
    int foodY;
    Random random = new Random();

    //贪吃蛇死亡判断
    boolean isFail = false;

    //积分系统
    int score;

    //初始化小蛇
    public void init() {
        length = 3;
        //头部坐标
        snakeX[0] = 100;
        snakeY[0] = 100;

        //第一节身体坐标,因为我们要小蛇是横着的,所有Y轴坐标不变X变
        snakeX[1] = 75;
        snakeY[1] = 100;

        //第二节身体坐标
        snakeX[2] = 50;
        snakeY[2] = 100;

        //初始化的时候初始化食物的坐标,边界为850,650
        foodX = 25 + 25 * random.nextInt(34);
        foodY = 75 + 25 * random.nextInt(24);

        score=0;

    }

    //创建构造方法
    public GamePanel() {
        init();
        //将键盘焦点聚集在这个游戏上
        this.setFocusable(true);

        //实现监听
        this.addKeyListener(this);

        //初始化要运行计时器,不然也调用不了actionPerformed方法
        timer.start();
    }

    //画板,画界面,画蛇
    //Graphic 可以理解为画笔
    @Override
    protected void paintComponent(Graphics g) {
        //清屏
        super.paintComponent(g);
        this.setBackground(Color.WHITE);
        //这里代表取出data类的header属性调用paintIcon的API方法进行添加到这个this面板
        Data.header.paintIcon(this, g, 25, 11);

        //绘制游戏的区域
        g.fillRect(25, 75, 850, 600);

        //画一条静态小蛇
        if (direction.equals(Direction.UP.direct)) {
            Data.up.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction.equals(Direction.DOWN.direct)) {
            Data.down.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction.equals(Direction.LEFT.direct)) {
            Data.left.paintIcon(this, g, snakeX[0], snakeY[0]);
        } else if (direction.equals(Direction.RiGHT.direct)) {
            Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);
        }

        //body下面就是使用身体图片 我们添加一个循环,可以随着长度添加渲染
        // Data.body.paintIcon(this,g,snakeX[1],snakeY[1]);
        // Data.body.paintIcon(this,g,snakeX[2],snakeY[2]);

        for (int i = 1; i < length; i++) {
            //蛇的长度通过length控制
            Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);
        }

        //画笔渲染食物
        Data.food.paintIcon(this, g, foodX, foodY);

        //画积分
        g.setColor(Color.WHITE);
        g.setFont(new Font("微软雅黑", Font.BOLD, 18));
        g.drawString("长度"+length,750,35);
        g.drawString("分数"+score,750,50);

        //如果游戏未开始
        if (!isStart) {
            g.setColor(Color.WHITE);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("按下空格开始游戏", 300, 300);
        }

        //失败提醒
        if (isFail) {
            g.setColor(Color.RED);
            g.setFont(new Font("微软雅黑", Font.BOLD, 40));
            g.drawString("游戏失败,按下空格重新开始", 200, 300);
        }
    }

    //按下未释放就行
    @Override
    public void keyPressed(KeyEvent e) {
        //接收键盘输入,获取键
        int keyCode = e.getKeyCode();

        if (keyCode == KeyEvent.VK_SPACE) {
            //游戏失败判断
            if (isFail) {
                isFail = false;
                //失败重开初始化
                init();
            } else {
                //按下可以暂停或者开始
                isStart = !isStart;
            }

            //刷新这个界面
            repaint();
        }

        //如果是当前反方向不执行
        //键盘控制走向
        if (keyCode == KeyEvent.VK_LEFT && !direction.equals(Direction.LEFT.direct)
                && !direction.equals(Direction.RiGHT.direct)) {
            direction = Direction.LEFT.direct;
        } else if (keyCode == KeyEvent.VK_RIGHT && !direction.equals(Direction.LEFT.direct)
                && !direction.equals(Direction.RiGHT.direct)) {
            direction = Direction.RiGHT.direct;
        } else if (keyCode == KeyEvent.VK_UP && !direction.equals(Direction.DOWN.direct)
                && !direction.equals(Direction.UP.direct)) {
            direction = Direction.UP.direct;
        } else if (keyCode == KeyEvent.VK_DOWN && !direction.equals(Direction.DOWN.direct)
                && !direction.equals(Direction.UP.direct)) {
            direction = Direction.DOWN.direct;
        }
    }

    //监听时间帧,定时器

    //执行定时操作
    @Override
    public void actionPerformed(ActionEvent e) {
        //如果游戏是启动的,要移动
        if (isStart && !isFail) {
            //身体也要移动
            for (int i = length - 1; i > 0; i--) {
                snakeX[i] = snakeX[i - 1];
                snakeY[i] = snakeY[i - 1];
            }

            //头部方向判断走向,如果是向右
            if (direction.equals(Direction.RiGHT.direct)) {
                //头部右移
                snakeX[0] = snakeX[0] + 25;
                if (snakeX[0] > 850) {
                    //如果出了边界850,那么重置
                    snakeX[0] = 25;
                }
            }
            //如果是向左
            else if (direction.equals(Direction.LEFT.direct)) {
                //横坐标减少一格
                snakeX[0] = snakeX[0] - 25;
                //同样判断边界,并且从右边出现
                if (snakeX[0] < 25) {
                    snakeX[0] = 850;
                }
            } else if (direction.equals(Direction.UP.direct)) {
                snakeY[0] = snakeY[0] - 25;
                if (snakeY[0] < 75) {
                    snakeY[0] = 650;
                }
            } else if (direction.equals(Direction.DOWN.direct)) {
                snakeY[0] = snakeY[0] + 25;
                if (snakeY[0] > 650) {
                    snakeY[0] = 75;
                }
            }

            //食物坐标和头坐标重合后
            if (snakeX[0] == foodX && snakeY[0] == foodY) {
                //长度加一并且重新生成
                length++;

                //积分+10
                score+=10;
                foodX = 25 + 25 * random.nextInt(34);
                foodY = 75 + 25 * random.nextInt(24);
            }

            //结束判断,小蛇身体和头重合
            for (int i = 1; i < length; i++) {
                //遍历身体看是否重合
                if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) {
                    isFail = true;
                }
            }

            //移动完了一定要从渲染页面
            repaint();
        }
        //启动计时器,让时间动起来
        timer.start();
    }

    //释放某个键
    @Override
    public void keyReleased(KeyEvent e) {

    }

    //键盘按下弹起事件
    @Override
    public void keyTyped(KeyEvent e) {

    }
}